package com.gitee.wsl.mathematics.complex

import com.gitee.wsl.unit.angle.AngleUnit
import com.gitee.wsl.unit.angle.toRadians
import kotlin.math.atan2
import kotlin.math.sqrt

/**
 * Represents `double`-based complex number.
 *
 * @property re The real part.
 * @property im The imaginary part.
 */
data class Complex(val re: Double, val im: Double) {
    constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
    constructor(re: Number) : this(re.toDouble(), 0.0)

    override fun toString(): String = "($re + i * $im)"

    companion object
}

/**
 * This complex's conjugate.
 */
 val Complex.conjugate: Complex
    get() = Complex(re, -im)

/**
 * This complex's reciprocal.
 */
 val Complex.reciprocal: Complex
    get() {
        val scale = re * re + im * im
        return Complex(re / scale, -im / scale)
    }

/**
 * Absolute value of complex number.
 */
 val Complex.r: Double
    get() = sqrt(re * re + im * im)

/**
 * An angle between vector represented by complex number and X axis.
 */
 val Complex.theta: Double
    get() = atan2(im, re)

val Complex.angle: AngleUnit
    get() = theta.toRadians()

/**
 * Creates a complex number with real part equal to this real.
 *
 * @receiver the real part.
 * @return the new complex number.
 */
 fun Number.toComplex(): Complex = Complex(this)
